// #include <myhead.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <dirent.h>
// #include<pthread.h>
#include <semaphore.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <wait.h>
#include <time.h>
#include <sys/time.h>
// #include <sqlite3.h>
#include "tool.h"

int sockfd;
sem_t sem; // 保护xxx_stat和xxx_global 以及 文件读写
char auto_open = 0;
sem_t auto_sem; // 保护auto_open
sem_t copy_sem; // 保护通过线程传参的地址进行拷贝的数据的完整性

int main(int argc, char const *argv[])
{
	if (3 != argc)
	{
		printf("Usage: %s <ip> <port>\n", argv[0]);
		return -1;
	}
	// 信号量初始化
	sem_init(&sem, 0, 1);
	sem_init(&auto_sem, 0, 1);
	sem_init(&copy_sem, 0, 1);
	// 获取config文件中的数据
	myprotocol_t buf;
	if (read_config(&buf))
	{
		printf("read_config error\n");
		goto END1;
	}
	// 网络初始化
	sockfd = net_init(argv[1], atoi(argv[2]));
	if (sockfd < 0)
	{
		printf("net_init error\n");
		goto END1;
	}
	printf("连接成功\n");
	// 登录请求
	send(sockfd, &buf, sizeof(buf), 0);
	recv(sockfd, &buf, sizeof(buf), 0);
	if (buf.user_info.flag == 1)
	{
		pthread_t tid;
		myprotocol_t thread_buf;
		// 登录成功
		if (init_dev()) // 所有设备初始化
		{
			printf("有设备没初始化成功, 建议重启客户端\n");
		}
		// 显示并测量环境数据线程
		pthread_create(&tid, NULL, display_thread, NULL);
		pthread_detach(tid);
		// 维护环境状态线程 (需要首次测完并填入全局变量中 才能打开maintain线程 保证数据的有效性)
		pthread_create(&tid, NULL, maintain_dev_thread, NULL);
		pthread_detach(tid);
		while (1)
		{
			memset(&buf, 0, sizeof(buf));
			if (recv(sockfd, &buf, sizeof(buf), 0) <= 0)
			{
				printf("服务器断开\n");
				// continue;
				break;
			}
			thread_buf = buf;
			switch (buf.cmd)
			{
			case ISONLINE_REQ:
				// 发送心跳
				buf.cmd = ISONLINE_ACK;
				send(sockfd, &buf, sizeof(buf), 0);
				break;
			case GET_ENVVAL_REQ:
				// 获取环境数据
				printf("收到指令 \n");
				pthread_create(&tid, NULL, get_envdata_thread, (void *)&thread_buf); // 32位long和指针大小一样
				pthread_detach(tid);
				break;
			case SET_THRESHOLD_REQ: // 可以通过发相应的ACK 对面可以知道操作成功与否
				// 设置阈值
				pthread_create(&tid, NULL, set_threshold_thread, (void *)&thread_buf);
				pthread_detach(tid);
				break;
			case CONTROL_DEV_REQ:
				// 控制设备
				if (buf.auto_open)
				{
					sem_wait(&auto_sem);
					auto_open = 1;
					sem_post(&auto_sem);
				}
				else
				{
					sem_wait(&auto_sem);
					auto_open = 0;
					sem_post(&auto_sem);
				}
				pthread_create(&tid, NULL, control_dev_thread, (void *)&thread_buf);
				pthread_detach(tid);
				break;
			default:
				break;
			}
			sem_wait(&copy_sem);
			sem_post(&copy_sem);
		}
	}
	else
	{
		printf("登录失败\n");
		close(sockfd);
		return -1;
	}
END2:
	close(sockfd);
END1:
	sem_destroy(&sem);
	sem_destroy(&auto_sem);
	sem_destroy(&copy_sem);
	return 0;
}
